//    Copyright (C) Kherty.  All rights reserved.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Windows;
using System.Windows.Documents;
using System.Windows.Media;
using OpenLS.Core.Serialization;

namespace OpenLS.Drawing
{
    public class TextCharacterProperties : IOfficeXmlSerializableAs
    {
        private TextUnderlineFillBase _TextUnderlineFill;
        private TextUnderlineLine _TextUnderlineLine;
        private string altLang;
        private bool? b;
        private int? baseline; //\\percent
        private TextCapsType cap;
        private FontFamily cs;
        private bool dirty = true;
        private FontFamily ea;
        private EffectProperties effectProperties;
        private bool err;
        private FillProperties fFillProperties;
        private double? fontSize;
        private ColorBase highlight;
        private Hyperlink hlinkClick;
        private bool? i;
        private int? kern; //\\int+
        private bool _kumimoji;
        private string lang;
        private FontFamily latin;
        private LineProperties ln;
        private bool noProof;
        private bool normalizeH;
        private bool smtClean = true;
        private int smtId;
        private int? spc;
        private TextStrikeType strike;
        private FontFamily sym;
        private TextUnderlineType u;
        private OfficeArtExtensionList extLst;

        public Hyperlink HyperlinkClick
        {
            get { return hlinkClick; }
            set { hlinkClick = value; }
        }


        public double? FontSize
        {
            get { return fontSize; }
            set { fontSize = value; }
        }


        public FontFamily Latin
        {
            get { return latin; }
            set { latin = value; }
        }

        public FontFamily EastAsian
        {
            get { return ea; }
            set { ea = value; }
        }

        public FontFamily Cs
        {
            get { return cs; }
            set { cs = value; }
        }

        public FontFamily Sym
        {
            get { return sym; }
            set { sym = value; }
        }

        public bool Kumimoji
        {
            get { return _kumimoji; }
            set { _kumimoji = value; }
        }

        public string Language
        {
            get { return lang; }
            set { lang = value; }
        }

        public string AlternateLanguage
        {
            get { return altLang; }
            set { altLang = value; }
        }

        public bool? Bold
        {
            get { return b; }
            set { b = value; }
        }

        public bool? Italic
        {
            get { return i; }
            set { i = value; }
        }

        public TextUnderlineType Underline
        {
            get { return u; }
            set { u = value; }
        }

        public TextStrikeType Strike
        {
            get { return strike; }
            set { strike = value; }
        }

        public int? Kern
        {
            get { return kern; }
            set { kern = value; }
        }

        public TextCapsType Capitalization
        {
            get { return cap; }
            set { cap = value; }
        }

        public int? Spacing
        {
            get { return spc; }
            set { spc = value; }
        }

        public bool NormalizedHeight
        {
            get { return normalizeH; }
            set { normalizeH = value; }
        }

        public int? Baseline
        {
            get { return baseline; }
            set { baseline = value; }
        }

        public bool NoProof
        {
            get { return noProof; }
            set { noProof = value; }
        }

        public bool Dirty
        {
            get { return dirty; }
            set { dirty = value; }
        }

        public bool SpellingError
        {
            get { return err; }
            set { err = value; }
        }

        public bool SmartTagClean
        {
            get { return smtClean; }
            set { smtClean = value; }
        }

        public int SmartTagId
        {
            get { return smtId; }
            set { smtId = value; }
        }


        public LineProperties LineProperties
        {
            get { return ln; }
            set { ln = value; }
        }


        public FillProperties FillProperties
        {
            get { return fFillProperties; }
            set { fFillProperties = value; }
        }

        public EffectProperties EffectProperties
        {
            get { return effectProperties; }
            set { effectProperties = value; }
        }

        public ColorBase Highlight
        {
            get { return highlight; }
            set { highlight = value; }
        }

        public TextUnderlineLine TextUnderlineLine
        {
            get { return _TextUnderlineLine; }
            set { _TextUnderlineLine = value; }
        }

        public TextUnderlineFillBase TextUnderlineFill
        {
            get { return _TextUnderlineFill; }
            set { _TextUnderlineFill = value; }
        }

        public Style Style
        {
            get
            {
                Style result = new Style();
                foreach (Setter s in GetAllSetters())
                    result.Setters.Add(s);
                return result;
            }
        }

        #region IOfficeXmlSerializableAs Members

        void IOfficeXmlSerializableAs.ReadXmlAs(string name, ReadContext context)
        {
            using (var c = context.Read(name))
            {
                Kumimoji = c.GetOptionalBoolean("kumimoji", false);
                //Debug.WriteLine("Kumimoji = " + Kumimoji + c.Part.Uri);
                lang = c.GetOptionalString("lang");
                altLang = c.GetOptionalString("altLang");
                int? fs = c.GetOptionalInteger("sz");
                if (fs != null)
                {
                    FontSize = ((double) fs)/100d*4d/3d;
                }
                else
                    FontSize = null;
                //\\FontSize = c.GetOptionalInteger("sz");
                b = c.GetOptionalBoolean("b");
                i = c.GetOptionalBoolean("i", false);
                u = c.GetOptionalEnum("u", TextUnderlineType.None);
                strike = c.GetOptionalEnum("strike", TextStrikeType.NoStrike);
                kern = c.GetOptionalInteger("kern");
                cap = c.GetOptionalEnum("cap", TextCapsType.None);
                spc = c.GetOptionalInteger("spc");
                normalizeH = c.GetOptionalBoolean("normalizeH", false);
                baseline = c.GetOptionalInteger("baseline");
                noProof = c.GetOptionalBoolean("noProof", false);
                dirty = c.GetOptionalBoolean("dirty", true);
                err = c.GetOptionalBoolean("err", false);
                smtClean = c.GetOptionalBoolean("smtClean", true);
                smtId = c.GetOptionalInteger("smtId", 0);

                LineProperties = c.ReadOptionalElement<LineProperties>("ln");
                FillProperties = FillProperties.ReadFillProperties(c);
                EffectProperties = EffectProperties.ReadEffectProperties(c);
                Highlight = ColorBase.ReadOptionalColorAs("highlight", c);
                //\\ReadContext cc = new ReadContext(_reader, part, DrawingConstants.DrawingNamespaceUri);
                TextUnderlineLine = TextUnderlineLine.ReadTextUnderlineLine(c);
                TextUnderlineFill = TextUnderlineFillBase.ReadTextUnderlineFill(c); 
                //\\TextUnderlineLine
                //\\EG_TextUnderlineFill
                Latin = TextFont.ReadOptionalFontFamily("latin", c);
                EastAsian = TextFont.ReadOptionalFontFamily("ea", c);
                Cs = TextFont.ReadOptionalFontFamily("cs", c);
                Sym = TextFont.ReadOptionalFontFamily("sym", c);
                HyperlinkClick = c.ReadOptionalElementAs<Hyperlink>("hlinkClick");
                HyperlinkMouseOver = c.ReadOptionalElementAs<Hyperlink>("hlinkMouseOver");
                this.extLst = c.ReadOptionalElement<OfficeArtExtensionList>("extLst");
            }
        }

        protected Hyperlink HyperlinkMouseOver { get; set; }

        void IOfficeXmlSerializableAs.WriteXmlAs(string name, WriteContext context)
        {
            using (WriteContext c = context.Write(name))
            {
                c.SetOptionalBoolean("kumimoji", Kumimoji, false);
                c.SetOptionalString("lang", lang);
                c.SetOptionalString("altLang", altLang);
                if (FontSize != null)
                {
                    int fs = (int) Math.Round(FontSize.Value*100d/4d*3d);
                    c.SetInteger("sz", fs);
                }
                c.SetOptionalBoolean("b", b);
                c.SetOptionalBoolean("i", i);
                c.SetOptionalEnum("u", u, TextUnderlineType.None);
                c.SetOptionalEnum("strike", strike, TextStrikeType.NoStrike);
                c.SetOptionalInteger("kern", kern);
                c.SetOptionalEnum("cap", cap, TextCapsType.None);
                c.SetOptionalInteger("spc", spc);
                c.SetOptionalBoolean("normalizeH", normalizeH, false);
                c.SetOptionalInteger("baseline", baseline);
                c.SetOptionalBoolean("noProof", noProof, false);
                c.SetOptionalBoolean("dirty", dirty, true);
                c.SetOptionalBoolean("err", err, false);
                c.SetOptionalBoolean("smtClean", smtClean, true);
                c.SetOptionalInteger("smtId", smtId, 0);

                c.WriteOptionalElement(LineProperties);
                c.WriteOptionalElement(FillProperties);
                //\\FillProperties = FillProperties.ReadFillProperties(c);
                c.WriteOptionalElement(EffectProperties);
                if (highlight != null)
                    highlight.WriteXmlAs(c, "highlight");
                //\\ReadContext cc = new ReadContext(_reader, part, DrawingConstants.DrawingNamespaceUri);
                c.WriteOptionalElement(TextUnderlineLine);
                c.WriteOptionalElement(TextUnderlineFill);
                //\\TextUnderlineLine
                //\\EG_TextUnderlineFill
                if (Latin != null)
                    TextFont.WriteFontFamily(latin, "latin", c);
                TextFont.WriteOptionalFontFamily(EastAsian, "ea", c);
                TextFont.WriteOptionalFontFamily(cs, "cs", c);
                TextFont.WriteOptionalFontFamily(Sym, "sym", c);
                //\\latin
                //\\ea
                //\\cs

                //\\sym
                c.WriteOptionalElementAs(HyperlinkClick, "hlinkClick");
                c.WriteOptionalElementAs(HyperlinkMouseOver, "hlinkMouseOver");
                c.WriteOptionalElement(extLst);
            }
        }

        #endregion

        private IEnumerable<Setter> GetPropertyValues(ColorScheme colorScheme)
        {
            if (Bold != null)
                yield return new Setter(TextElement.FontWeightProperty, Bold.Value ? FontWeights.Bold : FontWeights.Normal);
            if (FillProperties != null)
                yield return (new Setter(TextElement.ForegroundProperty, FillProperties.ToBrush(colorScheme)));
            if (Latin != null)
                yield return new Setter(TextElement.FontFamilyProperty, Latin);
            if (FontSize != null)
                yield return new Setter(TextElement.FontSizeProperty, FontSize.Value);
            if (Italic != null)
                yield return
                    new Setter(TextElement.FontStyleProperty, Italic.Value ? FontStyles.Italic : FontStyles.Normal);
        }

        internal void ApplyTo(Inline inline)
        {
            foreach (Setter p in GetPropertyValues(null)) //\\//\\
                inline.SetValue(p.Property, p.Value);
            return;
            /*if (this.Bold)
                inline.FontWeight = FontWeights.Bold;
            if (this.Cs != null)
                inline.FontFamily = Cs;
            if (this.Latin != null)
            {
             //\\   inline.FontFamily = Latin;
            }
            if (this.Italic)
                inline.FontStyle = FontStyles.Italic;
            if (this.FillProperties != null)
                inline.Background = FillProperties.Brush;
            if (fontSize != null)
                inline.FontSize = FontSize.Value;
            */
        }

        private IEnumerable<Setter> GetAllSetters()
        {
            if (fontSize != null)
                yield return new Setter(TextElement.FontSizeProperty, fontSize.Value);
            if (latin != null)
                yield return new Setter(TextElement.FontFamilyProperty, latin);
            if (Bold != null)
                yield return
                    new Setter(TextElement.FontWeightProperty, Bold.Value ? FontWeights.Bold : FontWeights.Normal);
            if (Italic != null)
                yield return
                    new Setter(TextElement.FontStyleProperty, Italic.Value ? FontStyles.Italic : FontStyles.Normal);
        }
    }
}